package com.netease.rtcdemo;


import static com.netease.lava.api.IVideoRender.ScalingType.SCALE_ASPECT_BALANCED;
import static com.netease.lava.api.IVideoRender.ScalingType.SCALE_ASPECT_FIT;
import static com.netease.lava.nertc.sdk.NERtcConstants.MediaCodecMode.MEDIA_CODEC_HARDWARE;
import static com.netease.lava.nertc.sdk.NERtcConstants.MediaCodecMode.MEDIA_CODEC_SOFTWARE;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.netease.lava.api.IVideoRender;
import com.netease.lava.nertc.sdk.NERtcConstants;
import com.netease.lava.nertc.sdk.NERtcEx;
import com.netease.lava.nertc.sdk.NERtcParameters;
import com.netease.lava.nertc.sdk.audio.NERtcAudioStreamType;
import com.netease.lava.nertc.sdk.stats.NERtcAudioRecvStats;
import com.netease.lava.nertc.sdk.stats.NERtcAudioSendStats;
import com.netease.lava.nertc.sdk.stats.NERtcVideoRecvStats;
import com.netease.lava.nertc.sdk.stats.NERtcVideoSendStats;
import com.netease.lava.nertc.sdk.video.NERtcBeautyEffectType;
import com.netease.lava.nertc.sdk.video.NERtcEncodeConfig;
import com.netease.lava.nertc.sdk.video.NERtcRemoteVideoStreamType;
import com.netease.lava.nertc.sdk.video.NERtcScreenConfig;
import com.netease.lava.nertc.sdk.video.NERtcVideoConfig;
import com.netease.lava.nertc.sdk.video.NERtcVideoStreamType;
import com.netease.lava.nertc.sdk.video.NERtcVideoView;
import com.netease.lava.nertc.sdk.video.NERtcVirtualBackgroundSource;
import com.netease.lava.nertc.sdk.watermark.NERtcVideoWatermarkConfig;
import com.netease.lava.nertc.sdk.watermark.NERtcVideoWatermarkTimestampConfig;
import com.netease.rtcdemo.screen.ScreenCaptureService;


import java.lang.ref.WeakReference;
import java.util.HashMap;


public class multiChatActivity extends AppCompatActivity implements callbackDelegate{

    public static final String ROOM_CID_TAG = "key.room.cid";
    public static final String ROOM_NAME_TAG = "key.room.cname";

    private static final boolean DEBUG = true;
    private static final String TAG = "cameraDemo";
    private static MediaProjectionManager sManager;
    private LinearLayout videoLinearLayout;
    private NERtcVideoView landBigView;
    private ImageView muteBtn;
    private static boolean mIsMute = false;
    private ImageView enableVideoBtn;
    private static boolean mIsVideoEnable = true;
    private ImageView enableScreenBtn;
    private ImageView statistics;
    private static boolean mIsScreenEnable = false;
    private static final int REQUEST_CODE_SCREEN_CAPTURE = 10000;
    private static Intent mData;
    private GridLayout mGridLayout;
    private int mColumnCount = 2; //多少列
    private int mMultiDemoUsers = 6; //会议最多人数
    private LayoutInflater mInflater;
    private GridLayout fullScreenLayout;
    private int mScreenWidth;
    private ImageView setting;
    private int mScreenHeight;
    private static MultiChatUser mUserSelf;
    private static MultiChatUser mUserSelfSub;
    private boolean mIsPortrait = true;
    private boolean renderFullScreen = false; //是否全屏显示
    private long mUid;
    private NotificationManager notificationManager;
    private ScrollView scrollView;
    private SharedPreferences mPreferences;
    private static NERtcRemoteVideoStreamType mSubscribeStream = NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh;
    private static HashMap<String, MultiChatUser> mRemoteUserMap = new HashMap<>();
    private boolean firstSubstream = true;
    private int mScreenResolution;
    private int mScreenFrameRate;
    private static boolean needUpdateSetting;
    private boolean mEnableBeauty;
    Handler mHandler = new Handler(Looper.getMainLooper());
    private ImageView backBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.multichat_activity);
        NERtcCallback.getInstance().registerDelegate(this);
        GlobalRef.chatUiRef = new WeakReference<>(this);
        Resources resources = this.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        mScreenWidth = dm.widthPixels;
        mScreenHeight = dm.heightPixels;
        mIsPortrait = resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        setting = findViewById(R.id.setting);
        setting.setOnClickListener(v -> launchSetting());
        statistics = findViewById(R.id.statistics);
        statistics.setOnClickListener(v -> {
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setClass(multiChatActivity.this, WebViewActivity.class);
            startActivity(intent);
        });
        initViews();
        boolean mEnableWaterMark = mPreferences.getBoolean(getString(R.string.setting_enable_waterMark), false);
        if(mEnableWaterMark){
            NERtcVideoWatermarkConfig config = new NERtcVideoWatermarkConfig();
            config.watermarkType = NERtcVideoWatermarkConfig.WatermarkType.kNERtcWatermarkTypeTimestamp;
            config.timestampWatermark = new NERtcVideoWatermarkTimestampConfig();
            saveTimeStamp(config.timestampWatermark);
            int ret = NERtcEx.getInstance().setLocalVideoWatermarkConfigs(NERtcVideoStreamType.kNERtcVideoStreamTypeMain, config);
        }
        NERtcEx.getInstance().setupLocalVideoCanvas(mUserSelf.renderView);

        int virtualBackGround = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_background_config), "0"));
        if(virtualBackGround == 1) {
            NERtcVirtualBackgroundSource backgroundSource = new NERtcVirtualBackgroundSource(2, 0, "/storage/emulated/0/Pictures/img.png", 3);
            NERtcEx.getInstance().enableVirtualBackground(true, backgroundSource);
        }
        scrollView = findViewById(R.id.net_scroll_View);
        StatsHelper.getInstance().setSink(this);

        int enableQualityOb = Integer.parseInt(mPreferences.getString(getString(R.string.setting_quality_profile), "0"));
        StatsHelper.getInstance().setEnableQuality(enableQualityOb == 1);
    }

    private int colorToInt(String text) {
        int ret = 0xFFFFFFFF;
        try {
            ret = Color.parseColor(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }
    private void saveTimeStamp(NERtcVideoWatermarkTimestampConfig config) {
        if (config == null) {
            return;
        }
        config.fontColor = colorToInt("#ffffffff");
        config.wmColor = colorToInt("#88888888");
        config.wmAlpha = 1.0f;
        config.fontSize = 30;
        config.offsetX = 0;
        config.offsetY = 0;

    }
    public void updateSetting(){
        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        boolean simulcastState = mPreferences.getBoolean(getString(R.string.setting_simulcast_enable), false);
        boolean aiStreamState = mPreferences.getBoolean(getString(R.string.setting_video_definition_enable), false);
        boolean nevcState = mPreferences.getBoolean(getString(R.string.setting_nevc_enable), false);
        boolean hardWareState = mPreferences.getBoolean(getString(R.string.setting_hardware_code_enable), false);
        int Resolution = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_resolution), "3"));
        int FrameRate = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_framerate), "3"));
        NERtcEx.getInstance().enableDualStreamMode(simulcastState);
        setlocalVideoConfig(FrameRate, Resolution);

        NERtcParameters parameters = new NERtcParameters();
        if(aiStreamState){
            NERtcParameters.Key video4k = NERtcParameters.Key.createSpecializedKey("engine.video.enable_jnd");
            parameters.set(video4k, true);
        }else{
            NERtcParameters.Key video4k = NERtcParameters.Key.createSpecializedKey("engine.video.enable_jnd");
            parameters.set(video4k, false);
        }
        parameters.set(NERtcParameters.KEY_VIDEO_SEND_MODE, 0);
        if(nevcState) {
            NERtcParameters.Key based_264 = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_based_264");
            parameters.set(based_264, true);
            NERtcParameters.Key enc = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_enc");
            parameters.set(enc, true);
            NERtcParameters.Key dec = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_dec");
            parameters.set(dec, true);
            NERtcParameters.Key superres = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc_adaptive_superres");
            parameters.set(superres, true);
        }else {
            NERtcParameters.Key based_264 = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_based_264");
            parameters.set(based_264, false);
            NERtcParameters.Key enc = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_enc");
            parameters.set(enc, false);
            NERtcParameters.Key dec = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc2_dec");
            parameters.set(dec, false);
            NERtcParameters.Key superres = NERtcParameters.Key.createSpecializedKey("engine.video.enable_nevc_adaptive_superres");
            parameters.set(superres, false);
        }
        NERtcParameters.Key enableDevEnvPram = NERtcParameters.Key.createSpecializedKey("key_test_server_uri");
        parameters.set(enableDevEnvPram, true);
        if(hardWareState){
            parameters.set(NERtcParameters.KEY_VIDEO_ENCODE_MODE, MEDIA_CODEC_HARDWARE);
        }else {
            parameters.set(NERtcParameters.KEY_VIDEO_ENCODE_MODE, MEDIA_CODEC_SOFTWARE);
        }
        boolean serverRecordHost = mPreferences.getBoolean(getString(R.string.setting_server_record_host_key), false);
        parameters.set(NERtcParameters.KEY_SERVER_RECORD_SPEAKER, serverRecordHost);
        if(serverRecordHost) {
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_AUDIO, true);
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_VIDEO, true);
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_MODE, 0);
        }else{
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_AUDIO, false);
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_VIDEO, false);
            parameters.set(NERtcParameters.KEY_SERVER_RECORD_MODE, 0);
        }
        NERtcEx.getInstance().setParameters(parameters);

        int subStream = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_sub_config), "0"));
        if(subStream == 0){
            mSubscribeStream = NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh;
        }else{
            mSubscribeStream = NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeLow;
        }
        mEnableBeauty = mPreferences.getBoolean(getString(R.string.setting_enable_beauty), false);
        if(mEnableBeauty){
            NERtcEx.getInstance().startBeauty();
            NERtcEx.getInstance().enableBeauty(true);
            NERtcEx.getInstance().setBeautyEffect(NERtcBeautyEffectType.kNERtcBeautyWhiten, 1);
            NERtcEx.getInstance().setBeautyEffect(NERtcBeautyEffectType.kNERtcBeautySmooth, 1);
            NERtcEx.getInstance().setBeautyEffect(NERtcBeautyEffectType.kNERtcBeautySmallFace, 0.2f);
        }else{
            NERtcEx.getInstance().stopBeauty();
            NERtcEx.getInstance().enableBeauty(false);
        }
        boolean mEnableWaterMark = mPreferences.getBoolean(getString(R.string.setting_enable_waterMark), false);
        if(mEnableWaterMark){
            NERtcVideoWatermarkConfig config = new NERtcVideoWatermarkConfig();
            config.watermarkType = NERtcVideoWatermarkConfig.WatermarkType.kNERtcWatermarkTypeTimestamp;
            config.timestampWatermark = new NERtcVideoWatermarkTimestampConfig();
            saveTimeStamp(config.timestampWatermark);
            int ret = NERtcEx.getInstance().setLocalVideoWatermarkConfigs(NERtcVideoStreamType.kNERtcVideoStreamTypeMain, config);
        }else{
            NERtcEx.getInstance().setLocalVideoWatermarkConfigs(NERtcVideoStreamType.kNERtcVideoStreamTypeMain, null);
        }

        int virtualBackGround = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_background_config), "0"));
        if(virtualBackGround == 1) {
            NERtcVirtualBackgroundSource backgroundSource = new NERtcVirtualBackgroundSource(2, 0, "/storage/emulated/0/Pictures/img.png", 3);
            NERtcEx.getInstance().enableVirtualBackground(true, backgroundSource);
        }else if(virtualBackGround == 0) {
            NERtcVirtualBackgroundSource backgroundSource = new NERtcVirtualBackgroundSource(2, 0, "/storage/emulated/0/Pictures/img.png", 3);
            NERtcEx.getInstance().enableVirtualBackground(false, backgroundSource);
        }
        int audioProfile = Integer.parseInt(mPreferences.getString(getString(R.string.setting_audio_profile), "0"));
        int scenario = Integer.parseInt(mPreferences.getString(getString(R.string.setting_audio_scenario), "0"));
        NERtcEx.getInstance().setAudioProfile(audioProfile, scenario);

        int enableQualityOb = Integer.parseInt(mPreferences.getString(getString(R.string.setting_quality_profile), "0"));
        StatsHelper.getInstance().setEnableQuality(enableQualityOb == 1);
        if(enableQualityOb == 0){
            TextView capView = mUserSelf.rootView.findViewById(R.id.text_view_cap);
            capView.setText("");
            TextView text_view_v_res = mUserSelf.rootView.findViewById(R.id.text_view_v_res);
            text_view_v_res.setText("");
            TextView text_view_v_tx = mUserSelf.rootView.findViewById(R.id.text_view_v_tx);
            text_view_v_tx.setText("");
            TextView text_view_v_fps = mUserSelf.rootView.findViewById(R.id.text_view_v_fps);
            text_view_v_fps.setText("");
            TextView text_view_v_enc = mUserSelf.rootView.findViewById(R.id.text_view_v_enc);
            text_view_v_enc.setText("");
            TextView text_view_a_tx = mUserSelf.rootView.findViewById(R.id.text_view_a_tx);
            text_view_a_tx.setText("");
            TextView text_view_a_lost = mUserSelf.rootView.findViewById(R.id.text_view_a_lost);
            text_view_a_lost.setText("");
            TextView text_view_a_rtt = mUserSelf.rootView.findViewById(R.id.text_view_a_rtt);
            text_view_a_rtt.setText("");
            TextView text_view_volume = mUserSelf.rootView.findViewById(R.id.text_view_volume);
            text_view_volume.setText("");
        }

    }
    @Override
    public void onResume(){
        super.onResume();
        Log.d("qweqwe","onResume");
        if(needUpdateSetting) {
            updateSetting();
            needUpdateSetting = false;
        }
    }
    public void launchSetting() {
        needUpdateSetting = true;
        Intent intent = new Intent(this, SettingsUI.class);
        startActivity(intent);
    }

    private void addMySelf() {
        mUserSelf = new MultiChatUser();
        mUserSelf.userId = mUid;
        createUserUI(mUserSelf, false, true);
    }

    private void addMySelfSub() {
        MultiChatUser user = new MultiChatUser();
        user.userId = mUid;
        mUserSelfSub = user;
        createUserUI(user, false, false);
        NERtcEx.getInstance().setupLocalSubStreamVideoCanvas(user.renderView);
    }

    private void addRemoteUserIfNeed() {
        for (String key : mRemoteUserMap.keySet()) {
            if(mRemoteUserMap.get(key).firstSub){
                firstSubstream = false;
            }
            createRemoteUserRender(mRemoteUserMap.get(key).userId, true, key.contains("main"));
            if(key.contains("main")){
                NERtcEx.getInstance().setupRemoteVideoCanvas(mRemoteUserMap.get(key).renderView, mRemoteUserMap.get(key).userId);
            }else{
                NERtcEx.getInstance().setupRemoteSubStreamVideoCanvas(mRemoteUserMap.get(key).renderView, mRemoteUserMap.get(key).userId);
            }
            if(mIsPortrait){
                mRemoteUserMap.get(key).renderView.setScalingType(SCALE_ASPECT_FIT);
            }else{
                mRemoteUserMap.get(key).renderView.setScalingType(SCALE_ASPECT_BALANCED);
            }
        }
    }
    private void addRemoteUserIfNeedLand() {
        for (String key : mRemoteUserMap.keySet()) {
            if(key.contains("sub") && mRemoteUserMap.get(key).firstSub){
                firstSubstream = false;
                mRemoteUserMap.get(key).renderView = findViewById(R.id.view1);
                NERtcEx.getInstance().setupRemoteSubStreamVideoCanvas(mRemoteUserMap.get(key).renderView, mRemoteUserMap.get(key).userId);
            }
          else if(key.contains("main")){
              mRemoteUserMap.get(key).renderView = addUserViewLand(key);
              NERtcEx.getInstance().setupRemoteVideoCanvas(mRemoteUserMap.get(key).renderView, mRemoteUserMap.get(key).userId);
          }else{
              mRemoteUserMap.get(key).renderView = addUserViewLand(key);
              NERtcEx.getInstance().setupRemoteSubStreamVideoCanvas(mRemoteUserMap.get(key).renderView, mRemoteUserMap.get(key).userId);
          }
            if(mIsPortrait){
                mRemoteUserMap.get(key).renderView.setScalingType(SCALE_ASPECT_FIT);
            }else{
                mRemoteUserMap.get(key).renderView.setScalingType(SCALE_ASPECT_BALANCED);
            }
        }
    }

    private IVideoRender addUserViewLand(String key) {
        RelativeLayout renderLayout = (RelativeLayout) mInflater.inflate(R.layout.multi_render_layout, null);
        IVideoRender renderView = renderLayout.findViewById(R.id.multi_big_render_view);
        MultiChatUser user = mRemoteUserMap.get(key);
        if(user != null)
            user.rootView = renderLayout;
        videoLinearLayout.addView(renderLayout, getLinearLayout());
        if(user != null)
            user.renderView.setScalingType(SCALE_ASPECT_BALANCED);
        return renderView;
    }
    private void setlocalVideoConfig(int frameRate, int videoProfile) {
        int videoPrefer =  Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_profile), "0"));
        NERtcVideoConfig.NERtcDegradationPreference mSubVideoDegradation = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_DEFAULT;
        switch (videoPrefer) {
            case 0:
                mSubVideoDegradation = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_DEFAULT;
                break;
            case 1:
                mSubVideoDegradation = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_MAINTAIN_FRAMERATE;
                break;
            case 2:
                mSubVideoDegradation = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_MAINTAIN_QUALITY;
                break;
            case 3:
                mSubVideoDegradation = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_BALANCED;
                break;
            default:
                break;
        }
        NERtcVideoConfig config = new NERtcVideoConfig();
        config.degradationPrefer = mSubVideoDegradation;
        config.frameRate = NERtcEncodeConfig.NERtcVideoFrameRate.values()[frameRate];
        config.videoProfile = videoProfile + 1;
        NERtcEx.getInstance().setLocalVideoConfig(config);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("qweqwe","onDestroy" );
        NERtcCallback.getInstance().removeDelegate();
        GlobalRef.chatUiRef = null;
    }
    private void requestScreenCapture() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && sManager == null) {
            startActivityForResult(createScreenCaptureIntent(this), REQUEST_CODE_SCREEN_CAPTURE);
        } else {
            startScreenCapture(mData);
        }
    }
    private void stopScreenCapture() {
        if (ScreenCaptureService.getInstance().mScreenService == null) {
            Toast.makeText(this, "屏幕录制服务为空", Toast.LENGTH_SHORT).show();
            return;
        }
        // 停止屏幕共享
        ScreenCaptureService.getInstance().mScreenService.stopScreenCapture();
        removeLocalSub();
    }
    private void addUser(long uid, String key) {
        if (mRemoteUserMap.get(key) == null) {
            MultiChatUser user = new MultiChatUser();
            user.userId = uid;
            mRemoteUserMap.put(key, user);
        }
    }
    private void createRemoteUserRender(long uid, boolean force, boolean mainStream) {
        String key = uid + "";
        if(mainStream)
            key = key + "_main";
        else
            key = key + "_sub";
        if (mRemoteUserMap.get(key) == null ||  force) {
            addUser(uid, key);
            MultiChatUser user = mRemoteUserMap.get(key);
            if (user != null) {
                createUserUI(user, force, mainStream);
            }
        }

        if(mainStream) {
            NERtcEx.getInstance().subscribeRemoteVideoStream(uid, mSubscribeStream, true);
            NERtcEx.getInstance().setupRemoteVideoCanvas(mRemoteUserMap.get(key).renderView, uid);
        }else {
            NERtcEx.getInstance().subscribeRemoteSubStreamVideo(uid, true);
            NERtcEx.getInstance().setupRemoteSubStreamVideoCanvas(mRemoteUserMap.get(key).renderView, uid);
        }
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static Intent createScreenCaptureIntent(Context context) {
        sManager = (MediaProjectionManager) context.getSystemService(
                Context.MEDIA_PROJECTION_SERVICE);
        return sManager.createScreenCaptureIntent();
    }

    private void toggleScreenCapture() {
        if (!mIsScreenEnable) {
            requestScreenCapture();
        } else {
            stopScreenCapture();
            mIsScreenEnable = false;
            NERtcEx.getInstance().setupLocalSubStreamVideoCanvas(null);
        }
    }
    private void initViews() {
        if(mIsPortrait){
            fullScreenLayout = findViewById(R.id.full_screen_view);
            fullScreenLayout.removeAllViews();
            mGridLayout = findViewById(R.id.multi_grid_layout);

            mGridLayout.setRowCount(mMultiDemoUsers / mColumnCount);
            mGridLayout.setColumnCount(mColumnCount);
        }else{
            videoLinearLayout = findViewById(R.id.videoLinearLayout);
            landBigView = findViewById(R.id.view1);
        }
        mInflater = LayoutInflater.from(this);
        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        int subStream = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_sub_config), "0"));
        if(subStream == 0){
            mSubscribeStream = NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeHigh;
        }else{
            mSubscribeStream = NERtcRemoteVideoStreamType.kNERtcRemoteVideoStreamTypeLow;
        }
        mScreenResolution = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_screen_resolution), "3"));
        mScreenFrameRate = Integer.parseInt(mPreferences.getString(getString(R.string.setting_video_screen_framerate), "3"));
        muteBtn = findViewById(R.id.item1);
        if(mIsMute) {
            muteBtn.setImageResource(R.drawable.unmute);
        }else{
            muteBtn.setImageResource(R.drawable.mute);
        }
        muteBtn.setOnClickListener(v -> {
            if(mIsMute) {
                NERtcEx.getInstance().muteLocalAudioStream(false);
                muteBtn.setImageResource(R.drawable.mute);
            }else{
                NERtcEx.getInstance().muteLocalAudioStream(true);
                muteBtn.setImageResource(R.drawable.unmute);
            }
            mIsMute = !mIsMute;
        });
        enableVideoBtn = findViewById(R.id.item2);
        if(mIsVideoEnable) {
            enableVideoBtn.setImageResource(R.drawable.nocamera);
        }else{
            enableVideoBtn.setImageResource(R.drawable.camera);
        }
        enableVideoBtn.setOnClickListener(v -> {
            if(mIsVideoEnable) {
                NERtcEx.getInstance().enableLocalVideo(false);
                mUserSelf.renderView.clearImage();
                enableVideoBtn.setImageResource(R.drawable.camera);
            }else{
                NERtcEx.getInstance().enableLocalVideo(true);
                enableVideoBtn.setImageResource(R.drawable.nocamera);
            }
            mIsVideoEnable = !mIsVideoEnable;
        });

        enableScreenBtn = findViewById(R.id.item3);
        if(mIsScreenEnable) {
            enableScreenBtn.setImageResource(R.drawable.noscreen);
        }else{
            enableScreenBtn.setImageResource(R.drawable.screen);
        }
        enableScreenBtn.setOnClickListener(v -> {
            if(mIsScreenEnable) {
                enableScreenBtn.setImageResource(R.drawable.screen);
            }else{
                enableScreenBtn.setImageResource(R.drawable.noscreen);
            }
            toggleScreenCapture();
        });
            backBtn = findViewById(R.id.back);
        if(backBtn != null) {
            backBtn.setOnClickListener(v -> {
                mRemoteUserMap.clear();
                NERtcEx.getInstance().leaveChannel();
                StatsHelper.getInstance().setSink(null);
                NERtcEx.getInstance().setVideoCallback(null, false);
                finish();
            });
        }

        //
        if(mIsPortrait) {
            String cname = getIntent().getStringExtra(ROOM_NAME_TAG);
            long cid = getIntent().getLongExtra(ROOM_CID_TAG, 0);
            String title = "cid:" + cid + "-" + cname;
            TextView titleView = findViewById(R.id.textView);
            titleView.setText(title);
        }

        if(mIsPortrait) {
            addMySelf();
            addRemoteUserIfNeed();
            if(mUserSelfSub != null)
                addMySelfSub();
        }else{
            addMySelf();
            if(mUserSelfSub != null)
                addMySelfSub();
            addRemoteUserIfNeedLand();
        }

    }
    private void destroyUserUI(MultiChatUser user) {
        if (user != null) {
            if (user.renderView != null) {
                user.renderView.clearImage();
                ((NERtcVideoView)user.renderView).release();
                user.renderView = null;
            }
            if(mIsPortrait) {
                if (user.rootView != null) {
                    mGridLayout.removeView(user.rootView);
                    user.rootView = null;
                }
            }else{
                if (user.rootView != null) {
                    videoLinearLayout.removeView(user.rootView);
                    videoLinearLayout.requestLayout();
                    user.rootView = null;
                }
            }
        }
    }
    private void removeUser(long uid, boolean mainStream) {
        String key = uid + "";
        if(mainStream)
            key = key + "_main";
        else
            key = key + "_sub";
        MultiChatUser user = mRemoteUserMap.get(key);
        destroyUserUI(user);
        if(user!=null && user.firstSub){
            firstSubstream = true;
            if(landBigView != null)
                landBigView.clearImage();
        }
        mRemoteUserMap.remove(key);
    }

    private void clearImg(long uid, boolean mainStream) {
        String key = uid + "";
        if(mainStream)
            key = key + "_main";
        else
            key = key + "_sub";
        MultiChatUser user = mRemoteUserMap.get(key);
        if(user!=null && user.firstSub){
            if(landBigView != null)
                landBigView.clearImage();
        }else if(user!=null){
            user.renderView.clearImage();
        }
    }

    private void removeLocalSub(){
        destroyUserUI(mUserSelfSub);
        mUserSelfSub = null;
        NERtcEx.getInstance().setupLocalSubStreamVideoCanvas(null);
    }

    @Override
    public void onJoinChannel(int result, long channelId, long elapsed, long uid) {

    }

    @Override
    public void onDisconnect(int reason) {
        Log.d("qweqwe", "onDisconnect: reason:" + reason);

        Toast.makeText(this, "连接断开", Toast.LENGTH_SHORT).show();
        finish();

        mRemoteUserMap.clear();
        StatsHelper.getInstance().setSink(null);
        NERtcEx.getInstance().setVideoCallback(null, false);
    }

    @Override
    public void onUserJoined(long uid) {
        createRemoteUserRender(uid, false, true);
    }

    @Override
    public void onUserLeave(long uid, int reason) {
        removeUser(uid, true);
        removeUser(uid ,false);
    }

    @Override
    public void onUserVideoStart(long uid, int maxProfile) {
    }

    @Override
    public void onUserVideoStop(long uid) {
        clearImg(uid, true);
    }

    @Override
    public void onUserSubStreamVideoStart(long uid, int maxProfile) {
        createRemoteUserRender(uid, false, false);
    }

    @Override
    public void onUserSubStreamVideoStop(long uid) {
        removeUser(uid, false);
    }

    @Override
    public void onLocalVideoStats(NERtcVideoSendStats stats) {
        for(int i = 0;i < stats.videoLayers.size();i++){
            if(stats.videoLayers.get(i).layerType == 1){
                TextView capView = mUserSelf.rootView.findViewById(R.id.text_view_cap);
                capView.setText("-cap: " + stats.videoLayers.get(i).capWidth + "x" + stats.videoLayers.get(i).capHeight);

                TextView text_view_v_res = mUserSelf.rootView.findViewById(R.id.text_view_v_res);
                text_view_v_res.setText("-v-res: " + stats.videoLayers.get(i).width + "x" + stats.videoLayers.get(i).height);

                TextView text_view_v_tx = mUserSelf.rootView.findViewById(R.id.text_view_v_tx);
                text_view_v_tx.setText("-v-tx: " + stats.videoLayers.get(i).sendBitrate + "kbps");

                TextView text_view_v_fps = mUserSelf.rootView.findViewById(R.id.text_view_v_fps);
                text_view_v_fps.setText("-v-fps: " + stats.videoLayers.get(i).sentFrameRate + "fps");

                TextView encoderName = mUserSelf.rootView.findViewById(R.id.text_view_v_enc);
                encoderName.setText("-v-enc: " + stats.videoLayers.get(i).encoderName);

            }
        }

    }

    @Override
    public void onRemoteVideoStats(NERtcVideoRecvStats[] statsArray) {
        for(int i = 0;i < statsArray.length;i++){
            String key = statsArray[i].uid + "";
            for(int j = 0;j < statsArray[i].layers.size();j++){
                String innerKey = "";
                if(statsArray[i].layers.get(j).layerType == 1){
                    innerKey = key + "_main";
                }else if(statsArray[i].layers.get(j).layerType == 2){
                    innerKey = key + "_sub";
                }
                Log.d("qweqwe", "innerKey:" + innerKey);
                MultiChatUser user = mRemoteUserMap.get(innerKey);
                if(user == null)
                    return;
                View rootView = mRemoteUserMap.get(innerKey).rootView;

                TextView capView = rootView.findViewById(R.id.text_view_cap);
                capView.setText("-v-res: " + statsArray[i].layers.get(j).width + "x" + statsArray[i].layers.get(j).height);

                TextView text_view_v_tx = rootView.findViewById(R.id.text_view_v_res);
                text_view_v_tx.setText("-v-rx: " + statsArray[i].layers.get(j).receivedBitrate + "kbps");

                TextView text_view_v_fps = rootView.findViewById(R.id.text_view_v_tx);
                text_view_v_fps.setText("-v-fps: " + statsArray[i].layers.get(j).fps + "fps");

                TextView encoderName = rootView.findViewById(R.id.text_view_v_fps);
                encoderName.setText("-v-dec: " + statsArray[i].layers.get(j).decoderName);

            }
        }
    }

    @Override
    public void onLocalAudioStats(NERtcAudioSendStats stats) {
        Log.d("qweqwe", stats.audioLayers.toString());
        for(int i = 0;i < stats.audioLayers.size();i++){
            if(stats.audioLayers.get(i).streamType == NERtcAudioStreamType.kNERtcAudioStreamTypeMain){
                TextView text_view_a_tx = mUserSelf.rootView.findViewById(R.id.text_view_a_tx);
                text_view_a_tx.setText("-a-tx:" + stats.audioLayers.get(i).kbps + "kbps sr:" + stats.audioLayers.get(i).sentSampleRate);

                TextView text_view_a_lost = mUserSelf.rootView.findViewById(R.id.text_view_a_lost);
                text_view_a_lost.setText("-a-lost:" + stats.audioLayers.get(i).lossRate);

                TextView text_view_a_rtt = mUserSelf.rootView.findViewById(R.id.text_view_a_rtt);
                text_view_a_rtt.setText("-a-rtt:" + stats.audioLayers.get(i).rtt);

                TextView text_view_volume = mUserSelf.rootView.findViewById(R.id.text_view_a_rtt);
                text_view_volume.setText("-volume:" + stats.audioLayers.get(i).volume);
            }
        }
    }

    @Override
    public void onRemoteAudioStats(NERtcAudioRecvStats[] statsArray) {
        for(int i = 0;i < statsArray.length;i++){
            String key = statsArray[i].uid + "";
            for(int j = 0;j < statsArray[i].layers.size();j++){
                String innerKey = "";
                if(statsArray[i].layers.get(j).streamType == NERtcAudioStreamType.kNERtcAudioStreamTypeMain){
                    innerKey = key + "_main";
                }else if(statsArray[i].layers.get(j).streamType == NERtcAudioStreamType.kNERtcAudioStreamTypeSub){
                    innerKey = key + "_sub";
                }
                if(mRemoteUserMap.get(innerKey) == null)
                    return;
                View rootView = mRemoteUserMap.get(innerKey).rootView;

                TextView text_view_volume = rootView.findViewById(R.id.text_view_a_rtt);
                text_view_volume.setText("-volume:" + statsArray[i].layers.get(j).volume);
            }
        }
    }

    private class MultiChatUser {
        long userId;
        View rootView;
        IVideoRender renderView;
        int view_width;
        int view_height;
        boolean firstSub;
    }
    private void createUserUI(MultiChatUser user, boolean force, boolean mainStream) {
        if (user.renderView == null || force) {
            RelativeLayout renderLayout = (RelativeLayout) mInflater.inflate(R.layout.multi_render_layout, null);
            user.rootView = renderLayout;
            user.renderView = renderLayout.findViewById(R.id.multi_big_render_view);
            renderLayout.setTag(user.userId);
            if(mIsPortrait){
                mGridLayout.addView(renderLayout, getGridLayout(user));
                mGridLayout.requestLayout();
                setTagInner(user.userId, mGridLayout.indexOfChild(renderLayout), 0, renderLayout);
                user.renderView.setScalingType(SCALE_ASPECT_FIT);
                if(user.userId != mUserSelf.userId && !mainStream && firstSubstream && !force){
                    firstSubstream = false;
                    user.firstSub = true;
                }
            }else{
                if(user.userId != mUserSelf.userId && !mainStream && firstSubstream){
                    firstSubstream = false;
                    user.firstSub = true;
                    user.renderView = landBigView;
                }else{
                    videoLinearLayout.addView(renderLayout, getLinearLayout());
                    videoLinearLayout.requestLayout();
                    setTagInner(user.userId, videoLinearLayout.indexOfChild(renderLayout), 0, renderLayout);
                }
                user.renderView.setScalingType(SCALE_ASPECT_BALANCED);
            }
        }
    }
    private class RenderViewTag {
        //Rtc uid.
        long uid;
        // index in mGridLayout.
        int index;
        //0: main, 1: sub
        int streamType;
    }
    private void setTagInner(long uid, int index, int streamType, View renderView) {
        RenderViewTag viewTag = new RenderViewTag();
        viewTag.index = index;
        viewTag.uid = uid;
        viewTag.streamType = streamType;
        renderView.setTag(viewTag);
        // renderView.setOnLongClickListener(v -> {

        //     Log.i(TAG, "user long click render view.");
        //     RenderViewTag viewTag1 = (RenderViewTag) renderView.getTag();

        //     boolean isFullScreen = fullScreenLayout.getChildCount() > 0;
        //     if (isFullScreen) {
        //         clearFullScreenRenderView();
        //     } else {
        //         setFullScreenFromUserClick(viewTag1.index);
        //     }
        //     return false;
        // });
        // 创建 GestureDetector 实例
       GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                Log.d(TAG, "onDown detected");
                return true;
            }

           @Override
           public boolean onDoubleTap(MotionEvent e) {
                Log.d(TAG, "onDoubleTap detected");
               // 双击事件处理
               //Toast.makeText(multiChatActivity.this, "双击事件", Toast.LENGTH_SHORT).show();
            RenderViewTag viewTag1 = (RenderViewTag) renderView.getTag();

            boolean isFullScreen = fullScreenLayout.getChildCount() > 0;
            if (isFullScreen) {
                clearFullScreenRenderView();
            } else {
                setFullScreenFromUserClick(viewTag1.index);
            }

               return true;  // 表示事件已被处理
           }
       });

        // 设置检测器属性
        gestureDetector.setIsLongpressEnabled(false);  // 禁用长按检测

        // 为 RenderView 设置触摸监听器
        renderView.setOnTouchListener(new View.OnTouchListener() {
        
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                //                         // 确保父视图不拦截触摸事件
                // v.getParent().requestDisallowInterceptTouchEvent(true);

                boolean handled = gestureDetector.onTouchEvent(event);
                Log.d(TAG, "gestureDetector.onTouchEvent returned: " + handled);
                return handled;
            }
       });
    }
    private void clearFullScreenRenderView() {
        try {
            int count = fullScreenLayout.getChildCount();
            for(int i = 0;i < count;i++) {
                for(int j = 0;j < fullScreenLayout.getChildCount();j++){
                    View renderView = fullScreenLayout.getChildAt(j);
                    RenderViewTag viewTag = (RenderViewTag) renderView.getTag();
                    if(viewTag.index == i){
                        fullScreenLayout.removeViewAt(j);
                        mGridLayout.addView(renderView, viewTag.index, getGridLayout(null));
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void setFullScreenFromUserClick(int index) {
        try {
            fullScreenLayout.removeAllViews();
            int childCount = mGridLayout.getChildCount(); // 获取子视图的数量
            for(int i = 0;i < childCount; i++) {
                View renderView = mGridLayout.getChildAt(0);
                mGridLayout.removeViewAt(0);
                fullScreenLayout.addView(renderView, mScreenWidth, mScreenHeight);
            }
            // 滑动到指定的 View
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (index >= 0 && index < fullScreenLayout.getChildCount()) {
                        View targetView = fullScreenLayout.getChildAt(index);
                        int y = targetView.getTop();
                        scrollView.scrollTo(0, y);
                    }
                }
            },10);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private GridLayout.LayoutParams getGridLayout(MultiChatUser user) {
        GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
        layoutParams.leftMargin = 2;
        layoutParams.topMargin = 2;
        layoutParams.bottomMargin = 2;
        layoutParams.rightMargin = 2;
        if (renderFullScreen) {
            layoutParams.width = mIsPortrait ? mScreenWidth - 4 : mScreenHeight - 4;
            layoutParams.height = mIsPortrait ? mScreenHeight - 4 : mScreenWidth - 4;
            return layoutParams;
        }
        layoutParams.width = mScreenWidth / mColumnCount - 4;
        switch (mMultiDemoUsers) {
            case 6:
                layoutParams.height = mScreenHeight / (mMultiDemoUsers / mColumnCount) - 4;
                break;
            case 12:
            case 16:
            case 24:
                if (mIsPortrait) {
                    layoutParams.height = layoutParams.width * 4 / 3;
                } else {
                    layoutParams.height = layoutParams.width * 3 / 4;
                }
                break;
            default:
                break;
        }
        if(user != null) {
            user.view_height = layoutParams.height;
            user.view_width = layoutParams.width;
        }
        return layoutParams;
    }

    private LinearLayout.LayoutParams getLinearLayout() {
        // 设置视图的宽度和高度
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mScreenHeight - 490, 300); // 设置布局参数

        return params;
    }

    @Override
    protected void onStart() {
        if (DEBUG) Log.d(TAG, "onStart:");
        super.onStart();

    }

    @Override
    protected void onStop() {
        if (DEBUG) Log.d(TAG, "onStop:");
        super.onStop();
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void startScreenCapture(Intent mediaProjectionPermissionResultData) {
        Log.d("qweqwe", "startScreenCapture");
        if (ScreenCaptureService.getInstance().mScreenService == null) {
            Toast.makeText(this, "屏幕录制服务启动失败", Toast.LENGTH_SHORT).show();
            return;
        }

        // 屏幕录制回调
        final MediaProjection.Callback mediaProjectionCallback = new MediaProjection.Callback() {
            @Override
            public void onStop() {
                super.onStop();
            }
        };

        NERtcScreenConfig screenProfile = new NERtcScreenConfig();
        screenProfile.videoProfile = mScreenResolution + 1;
        screenProfile.frameRate = NERtcEncodeConfig.NERtcVideoFrameRate.values()[mScreenFrameRate];
        // 开启屏幕共享
        int result = ScreenCaptureService.getInstance().mScreenService.startScreenCapture(screenProfile,
                mediaProjectionPermissionResultData, // 屏幕录制请求返回的Intent
                mediaProjectionCallback);

        if (result == NERtcConstants.ErrorCode.OK) {
            mIsScreenEnable = true;
        }
        addMySelfSub();
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        mData = data;
        if (requestCode == REQUEST_CODE_SCREEN_CAPTURE) {
            if (resultCode == RESULT_OK) {
                startScreenCapture(mData);
            } else {
                Toast.makeText(this, "拒绝了屏幕共享权限", Toast.LENGTH_SHORT).show();
            }
        }
    }
    @Override
    public void onBackPressed() {
        // 在这里执行您要处理的逻辑
        super.onBackPressed();
        mRemoteUserMap.clear();
        NERtcEx.getInstance().leaveChannel();
        StatsHelper.getInstance().setSink(null);
        NERtcEx.getInstance().setVideoCallback(null, false);
    }
}